// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin_JXGM ql1746365080@gmail.com
 * @Date: 2024-10-11 15:36:29
 * @LastEditors: qiulin 1746365080@qq.com
 * @LastEditTime: 2024-12-23 14:48:41
 * @FilePath: \SGFEM\Import\BDFImport\BulkData\Constraint\RSPLINEParser.cpp
 */

#include "RSPLINEParser.h"

#include <algorithm>
#include <cstdint>
#include <iostream>

#include "Utility/Logging/SGLogger.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Constraint/IRSPLINEService.h"

#include "Import/BDFImport/BDFParserBase.h"

BULKDATA_ENTRY_PARSER_REG (RSPLINE);

using namespace SG::DBManager;
using namespace SG::Import;
using namespace SG::DataStructure;
/*
// file://./../../Doc/MarkDown/BulkData/RSPLINE/RSPLINE.md>
*/

enum RSPLINEIndex : std::uint8_t
{
    RSPLINEIndex_EID = 1,
    RSPLINEIndex_DL = 2,  // Ratio of the diameter of the elastic tube to the sum of the lengths of all segments. (Real> 0.0; Default = 0.1)
    RSPLINEIndex_G1 = 3,
};
SG::DataStructure::Common::Status BDF::BULKDATA::ParseRSPLINE (const std::shared_ptr<SG::DBManager::DBServiceFactory>& dbServiceFactory,
                                                               std::vector<std::string>&                               dividedEntryInfo)

{
    SG::DataStructure::FEM::RSPLINEData tempData;

    // 设置初始默认值，设置默认的m_slender值为0.1
    tempData.m_slender = 0.1;

    // TODO(bug 001) 填写正确的 m_domainId 值，目前设置为1
    tempData.m_domainId = 1;

    // 解析固定数据：将分割的条目信息转换为相应的数值并赋值给 tempData 对象
    std::all_of (dividedEntryInfo[RSPLINEIndex_DL].begin (), dividedEntryInfo[RSPLINEIndex_DL].end (), [] (char c) { return c == ' '; })
        ? tempData.m_slender = 0.1
        : tempData.m_slender = convertToReal (dividedEntryInfo[RSPLINEIndex_DL]);
    // 转换 D/L 值为 double
    tempData.m_g1 = convertToI64 (dividedEntryInfo[RSPLINEIndex_G1]);   // 读取 G1 的 grid ID
    tempData.m_id = convertToI64 (dividedEntryInfo[RSPLINEIndex_EID]);  // 读取 EID 的元素 ID

    // 计算词条行数，每行包含 10 个字段
    size_t const rowNum           = dividedEntryInfo.size () / 10;
    size_t const endColumnIndex   = 9;  // 每行最后一个字段的下标
    size_t       beginColumnIndex = 4;  // 第一行从第4个字段开始处理

    // 标识符 isGID：用于区分当前正在处理的值是否为节点 ID（GID）
    bool isGID = true;

    // 临时对象，用于存储节点和分量的配对信息
    SG::DataStructure::FEM::RSPLINEData::NodeComponent tempNodeComponent;

    // 遍历每一行词条数据
    for (size_t curRow = 0; curRow < rowNum; curRow++)
    {
        // 如果不是第一行，则开始解析的列下标调整为1
        if (curRow != 0)
        {
            beginColumnIndex = 1;
        }

        // 遍历每行的每一个字段，从 beginColumnIndex 到 endColumnIndex
        for (size_t fieldsColumn = beginColumnIndex; fieldsColumn < endColumnIndex; fieldsColumn++)
        {
            // 计算当前字段的索引，基于当前行和列
            const size_t curIndex  = curRow * 10 + fieldsColumn;
            std::string& curStrKey = dividedEntryInfo[curIndex];

            // 检查当前字段是否为空
            bool const isEmpty = is_all_space (curStrKey);

            // 如果当前字段为空白，跳过处理逻辑
            if (isEmpty)
            {
                // 如果当前不是在处理 GID（即正在处理 DOF）
                if (!isGID)
                {
                    // 若 Ci 为空，设置节点的自由度 (DOF) 为 0，并保存节点信息
                    tempNodeComponent.m_dofs = 0;
                    tempData.m_items.push_back (tempNodeComponent);
                    isGID = !isGID;  // 转换标识符，准备下一个 GID
                }
                else
                {
                    break;  // 如果 GID 为空，则说明没有更多内容，退出循环
                }
            }
            else
            {
                        // 如果正在处理的是 DOF，则转换为 long long 并存储
                if (!isGID)
                {
                    tempNodeComponent.m_dofs = convertToI64 (curStrKey);
                    tempData.m_items.push_back (tempNodeComponent);  // 将节点信息添加到 tempData 中
                }
                // 否则处理的是 GID，转换为 long long 并存储
                else
                {
                    tempNodeComponent.m_nodeId = convertToI64 (curStrKey);
                }
                isGID = !isGID;  // 每处理一次切换 GID 与 DOF 解析标识符
            }
        }
    }

    // 最后一个网格点是第九个元素需要单独处理
    //  获取最后一个非空下标
    int lastNoEmptyIndex = findNonEmptyIndex (dividedEntryInfo, rowNum - 1);  // 最后一个非空filed的下标
    if (8 == (lastNoEmptyIndex % 10))
    {
        tempNodeComponent.m_dofs = 0;
        tempData.m_items.push_back (tempNodeComponent);
    }

    // 将解析得到的数据通过数据库服务工厂保存到数据库中
    return dbServiceFactory->get<IRSPLINEService> ()->Add (tempData);
}